package com.windy.i18n.resolver;

import com.windy.i18n.constant.LocaleType;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.i18n.SimpleLocaleContext;
import org.springframework.context.i18n.TimeZoneAwareLocaleContext;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.LocaleContextResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Created by liyufeng on 2022/5/15
 */
public class LangHeaderLocaleResolver implements LocaleContextResolver {
    private final List<Locale> supportedLocales = new ArrayList<>(4);

    private String headerName;

    @Nullable
    private Locale defaultLocale;

    public void setSupportedLocales(List<Locale> locales) {
        this.supportedLocales.clear();
        this.supportedLocales.addAll(locales);
    }

    public LangHeaderLocaleResolver() {
    }


    public List<Locale> getSupportedLocales() {
        return this.supportedLocales;
    }

    public void setDefaultLocale(@Nullable Locale defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    @Nullable
    public String getHeaderName() {
        return this.headerName;
    }

    public void setHeaderName(@Nullable String headerName) {
        this.headerName = headerName;
    }

    @Nullable
    public Locale getDefaultLocale() {
        return this.defaultLocale;
    }


    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        //String requestLang = request.getHeader(headerName);
        //测试改成从参数中拿
        String requestLang= request.getParameter(headerName);
        //todo
        //改成从上下文中拿到header?
        Locale locale;
        if (requestLang != null && !"".equals(requestLang)) {
            locale = LocaleType.getValue(requestLang);
        } else {
            locale = getDefaultLocale();
        }
        if (isSupportedLocale(locale)) {
            return locale;
        } else {
            return getDefaultLocale();
        }
    }

    private boolean isSupportedLocale(Locale locale) {
        List<Locale> supportedLocales = getSupportedLocales();
        return (supportedLocales.isEmpty() || supportedLocales.contains(locale));
    }

    @Override
    public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
        setLocaleContext(request, response, (locale != null ? new SimpleLocaleContext(locale) : null));
    }

    @Override
    public LocaleContext resolveLocaleContext(HttpServletRequest request) {
        return new TimeZoneAwareLocaleContext() {
            @Override
            @Nullable
            public Locale getLocale() {
                return resolveLocale(request);
            }

            @Override
            public TimeZone getTimeZone() {
                return getDefaultTimeZone();
            }
        };
    }

    @Override
    public void setLocaleContext(HttpServletRequest request, HttpServletResponse response, LocaleContext localeContext) {
        LocaleContextHolder.setLocaleContext(localeContext == null ? new SimpleLocaleContext(resolveLocale(request)) : localeContext, false);
    }

    @Nullable
    private TimeZone defaultTimeZone;

    public void setDefaultTimeZone(@Nullable TimeZone defaultTimeZone) {
        this.defaultTimeZone = defaultTimeZone;
    }

    @Nullable
    public TimeZone getDefaultTimeZone() {
        return this.defaultTimeZone;
    }
}
